﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Helpers;
using SharedTypes;

namespace AdaptationProject.Forms
{
    /// <summary>
    /// Класс реализует параметр алгоритма исполнительного файла, который
    /// может быть адаптирован.
    /// </summary>
    public class CmdParameter : IParameter, ICloneable
    {
        #region Members
        /// <summary>
        /// Порядковый номер параметра.
        /// </summary>
        private byte m_orderNum;

        /// <summary>
        /// Имя параметра.
        /// </summary>
        private string m_name;

        /// <summary>
        /// Условное связывание.
        /// </summary>
        private string m_conditionLink;

        /// <summary>
        /// Имя параметра.
        /// </summary>
        private string m_shortDescription;

        /// <summary>
        /// Описание параметра.
        /// </summary>
        private string m_description;

        /// <summary>
        /// Список допустимых значений параметра.
        /// </summary>
        private IList<AcceptableValue> m_acceptableValues;

        /// <summary>
        /// Текущее значение параметра.
        /// </summary>
        private AcceptableValue m_currentAcceptValues;

        /// <summary>
        /// Текущий параметр.
        /// </summary>
        private object m_currentValues;

        /// <summary>
        /// Значение после заданого значения.
        /// </summary>
        private string m_valueEnd;

        /// <summary>
        /// Разделитель.
        /// </summary>
        private string m_separator;

        /// <summary>
        /// Текущее значение по умолчанию.
        /// </summary>
        private object m_defaultValue;

        /// <summary>
        /// Является ли параметр ключевым
        /// </summary>
        private bool m_isParamKey;

        /// <summary>
        /// Тип параметра.
        /// </summary>
        private int m_type;

        /// <summary>
        /// Объект генератора случайных чисел.
        /// </summary>
        private static Random m_randomiser;
        #endregion /// Members

        #region Properties

        /// <summary>
        /// Порядковый номер параметра.
        /// </summary>
        public byte OrderNum
        {
            get { return m_orderNum; }
        }

        /// <summary>
        /// Имя параметра.
        /// </summary>
        public string Name
        {
            get { return m_name; }
        }

        /// <summary>
        /// Условное связывание.
        /// </summary>
        public string ConditionLink
        {
            get { return m_conditionLink; }
        }

        /// <summary>
        /// Краткое описание параметра.
        /// </summary>
        public string ShortDescription
        {
            get { return m_shortDescription; }
        }

        /// <summary>
        /// Описание параметра.
        /// </summary>
        public string Description
        {
            get { return m_description; }
        }

        /// <summary>
        /// Список допустимых значений параметра.
        /// </summary>
        public IList<AcceptableValue> AcceptableValues
        {
            get { return m_acceptableValues; }
        }

        /// <summary>
        /// Количество допустимых значений.
        /// </summary>
        public int NumOfAcceptableValues
        {
            get { return m_acceptableValues.Count; }
        }

        /// <summary>
        /// Текущий параметр.
        /// </summary>
        public AcceptableValue CurrentAcceptValue
        {
            get { return m_currentAcceptValues; }
            set { m_currentAcceptValues = value; }
        }

        /// <summary>
        /// Текущее значение параметра.
        /// </summary>
        public object CurrentValue
        {
            get { return m_currentValues; }
            set { m_currentValues = value; }
        }

        /// <summary>
        /// Значение после заданого значения.
        /// </summary>
        public string ValueEnd
        {
            get { return m_valueEnd; }
        }

        /// <summary>
        /// Разделитель.
        /// </summary>
        public string Separator
        {
            get { return m_separator; }
        }

        /// <summary>
        /// Значение по умолчанию.
        /// </summary>
        public object DefaultValue
        {
            get { return m_defaultValue; }
        }

        /// <summary>
        /// Является ли параметр ключевым
        /// </summary>
        public bool IsParamKey
        {
            get { return m_isParamKey; }
        }

        /// <summary>
        /// Тип параметра
        /// </summary>
        public int Type
        {
            get { return m_type; }
        }

        #endregion // Properties

        #region Constructor
        /// <summary>
        /// Конструктор.
        /// </summary>
        /// <param name="order">Порядковый номер.</param>
        /// <param name="name">Имя параметра.</param>
        /// <param name="description">Описание параметра.</param>
        /// <param name="values">Список допустимых значений.</param>
        /// <param name="defaultValue">Значение по умолчанию.</param>
        /// <param name="isParamKey">Является ли параметр ключевым.</param>
        /// <param name="isParamKey">Тип параметра.</param>
        public CmdParameter(byte order,
                            string name,
                            string conditionLink,
                            string shortDescription,
                            string description,
                            IList<AcceptableValue> values,
                            string valueEnd,
                            string separator,
                            object defaultValue,
                            bool isParamKey,
                            int type)
        {
            if (isParamKey)
            {
                this.m_name = name;
            }
            else
            {
                this.m_name = defaultValue.ToString();
            }
            
            m_conditionLink = conditionLink;
            m_orderNum = order;
            m_shortDescription = shortDescription;
            m_description = description;
            m_acceptableValues = values;
            m_currentValues = null;
            m_valueEnd = valueEnd;
            m_separator = separator;
            m_defaultValue = defaultValue;
            m_randomiser = new Random(DateTime.Now.Millisecond);
            m_isParamKey = isParamKey;
            m_type = type;
        }
        #endregion // Constructor

        #region Methods
        /// <summary>
        /// Функция, присваивающая параметра случайное значение если имеем несколько предложения для конкретного
        /// значения из списка допустимых.
        /// </summary>
        public void PlaceParamInRandomState()
        {
            int id = m_randomiser.Next(0, m_acceptableValues.Count/* - 1*/);
            CurrentAcceptValue = m_acceptableValues[id];
        }

        /// <summary>
        /// Функция, присваивающая параметра случайное значение
        /// из списка допустимых.
        /// </summary>
        public void PlaceValuesInRandomState()
        {
            PlaceParamInRandomState(); /// !!! Crutch
            int id = m_randomiser.Next(0, ((IList<object>)CurrentAcceptValue.values).Count/* - 1*/);
            CurrentValue = ((IList<object>)CurrentAcceptValue.values)[id];
        }

        /// <summary>
        /// Функция, создающая глубокую копию текущего объекта.
        /// </summary>
        /// <returns>Копия текущего объекта.</returns>
        public object Clone()
        {
            IList<AcceptableValue> values = new List<AcceptableValue>();
            foreach (AcceptableValue acceptableValue in m_acceptableValues)
            {
                AcceptableValue acceptValue = new AcceptableValue();
                acceptValue.values = ObjectCloner.CloneObject(acceptableValue.values);
                acceptValue.Percent = acceptableValue.Percent;

                values.Add(acceptValue);
            }
            CmdParameter toRet = new CmdParameter(m_orderNum,
                                                  m_name,
                                                  m_conditionLink,
                                                  m_shortDescription,
                                                  m_description,
                                                  values,
                                                  m_valueEnd,
                                                  m_separator,
                                                  ObjectCloner.CloneObject(m_defaultValue),
                                                  m_isParamKey,
                                                  m_type);
            toRet.m_currentValues = m_currentValues.ToString();
            return toRet;
        }
        #endregion // Methods
    }
}
